x11: Make selection handling work across screens
authorMatthias Clasen <mclasen@redhat.com>
Tue, 28 Jul 2015 03:18:27 +0000 (23:18 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 28 Jul 2015 03:20:53 +0000 (23:20 -0400)
When dealing with selection events, we might see windows from
other screens in the requestor field. The current x11 backend
code fails to wrap these in a foreign GdkWindow, since we
don't have the corresponding GdkScreen anymore. Work around
this by creating such 'foreign screens' on demand. We still
maintain the 1:1 relation between the display and the screen
returned by gdk_display_get_default_screen().

https://bugzilla.gnome.org/show_bug.cgi?id=721398

gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkdisplay-x11.h

index f2824b65bd75cb1e56a1064cce71e3bcc3354483..9bb27eecfb110150c4be937188c59f5e40c39553 100644 (file)
@@ -1959,6 +1959,7 @@ gdk_x11_display_finalize (GObject *object)
 
   /* Free all GdkScreens */
   g_object_unref (display_x11->screen);
+  g_list_free_full (display_x11->screens, g_object_unref);
 
   g_free (display_x11->startup_notification_id);
 
@@ -2035,12 +2036,36 @@ GdkScreen *
 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
                                      Window      xrootwin)
 {
-  GdkScreen *screen = gdk_display_get_default_screen (display);
+  GdkScreen *screen;
+  XWindowAttributes attrs;
+  gboolean result;
+  GdkX11Display *display_x11;
+  GList *l;
+
+  screen = gdk_display_get_default_screen (display);
 
   if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
     return screen;
 
-  return NULL;
+  display_x11 = GDK_X11_DISPLAY (display);
+
+  for (l = display_x11->screens; l; l = l->next)
+    {
+      screen = l->data;
+      if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
+        return screen;
+    }
+
+  gdk_x11_display_error_trap_push (display);
+  result = XGetWindowAttributes (display_x11->xdisplay, xrootwin, &attrs);
+  if (gdk_x11_display_error_trap_pop (display) || !result)
+    return NULL;
+
+  screen = _gdk_x11_screen_new (display, XScreenNumberOfScreen (attrs.screen));
+
+  display_x11->screens = g_list_prepend (display_x11->screens, screen);
+
+  return screen;
 }
 
 /**
index aadf255ba6dda8a915ea74a23566bb9e3fef1883..9b78f61d17cc544964786db768ebdd648bc679bd 100644 (file)
@@ -39,6 +39,7 @@ struct _GdkX11Display
   GdkDisplay parent_instance;
   Display *xdisplay;
   GdkScreen *screen;
+  GList *screens;
 
   GSource *event_source;